iT邦幫忙

2021 iThome 鐵人賽

DAY 17
1

今天處裡剩下的部分:checker 函式和它注入頁面的輔助函式。

checker

checker 函式基本上就是幫我們重複地跑無窮迴圈,每隔一段時間就去刷一下資料,然後如果有可加選的空位則提醒使用者。
在這裡提醒就是印到 console 上,但之後我們應該會讓它可以用通訊軟體通知。

async function checker(courses) {
    // 一樣,確認子頁面存在再操作
    await page.waitForSelector("#stfseldListDo");
    const child_page = await (await page.$("#stfseldListDo")).contentFrame();

    // 用無窮迴圈重複執行,直到想停止時手動結束程式
    while (true) {
        // 遍歷每個課程,檢查是否有可加選的課程
        for (let i = 0; i < courses.length; i++) {
            // 在子頁面中注入程式確認課程人數狀態,後方是帶入的查詢參數
            const data = await child_page.evaluate(injection.getInfo, courses[i].code, courses[i].class, courses[i].type, courses[i].form);
            courses[i].seats = data.限修人數 - data.已分發人數;
        }

        // 印出所有可加選課程
        console.log(
            "---\n" +
                courses
                    .filter((course) => course.seats > 0)
                    .map((course) => `${course.name} 還有 ${course.seats} 個空位`)
                    .join("\n")
        );

        // 冷卻時間,避免癱瘓系統
        await child_page.waitForTimeout(30 * 1000);
    }
}

因為學校系統可能有點年紀了,所以我們每刷完一次就冷卻 30 秒。

injection.getInfo

這個函式的用途是在頁面中建立一個查詢的 iframe,並解析 iframe 中資料後回傳至主要程式。

async function getInfo(code, group, type, form) {
    // 製造一個新的 iframe,就跟選課系統一樣
    const f = document.createElement("iframe");
    f.src = `https://cos1s.ntnu.edu.tw/AasEnrollStudent/CourseQueryCtrl?year=110&term=1&courseCode=${code}&courseGroup=${group}&deptCode=${type}&formS=${form}&classes1=&deptGroup=&action=showInfo`;
    document.body.appendChild(f);
    // 等待頁面載入完成,為了預防卡死 5 秒強制結束
    await new Promise((resolve) => {
        f.onload = resolve;
        setTimeout(resolve, 5000);
    });
    await new Promise((resolve) => setTimeout(resolve, 1000));
    // 用 try 來預防莫名其妙的錯誤
    try {
        // 取得 iframe 內的資料
        const raw = f.contentDocument.querySelector("#fieldcontainer-1010-targetEl").innerText;
        // 刪除 iframe,預防最後開太多 iframe 記憶體用量太大
        f.remove();
        // 將資料從文字中拆解出來
        // 組成一一對應,例如限修人數: 10, 已分發人數: 10
        const info = raw
            .replace(/[\s\n]+/g, "")
            .match(/\D+?:\d+/g)
            .map((x) => x.split(":"))
            .reduce((a, c) => {
                try {
                    a[c[0]] = +c[1];
                } catch {}
                return a;
            }, {});
        return info;
    } catch {
        return {};
    }
}

這樣,我們的程式就寫好了。
可以試試在 dev = true 的狀態跟 dev = false 的狀態有什麼差別。
在驗證碼辨識時可能會需要一點時間,可能會長至 30 秒。

下個章節

接下來,我們就要來讓這個程式串接 Chat Bot 了。


每日鐵人賽熱門 Top 10 (0930)

以 9/30 20:00 ~ 10/01 20:00 文章觀看數增加值排名

  1. +199 Day 1 無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  2. +184 Proxmox VE 安裝容器:Rocky Linux 8.4 及其它應用 (WordPress, Nextcloud, Odoo)
    • 作者: Jason Cheng (節省哥)
    • 系列:突破困境:企業開源虛擬化管理平台
  3. +156 Day 2 AWS 是什麼?又為何企業這麼需要 AWS 人才?
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  4. +155 Android學習筆記22
    • 作者: blossomgp3
    • 系列:Android kotlin &MVVM
  5. +154 [Day28] 戲弄老闆! 教你用Machine Learning將老闆玩弄於股掌之間!
    • 作者: lulu_meat
    • 系列:奇怪的知識增加了!原來程式還可以這樣用?!
  6. +147 Day 3 雲端四大平台比較:AWS . GCP . Azure . Alibaba
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  7. +140 Day 4 網路寶石:AWS VPC Region/AZ vs VPC/Subnet 關係介紹
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  8. +134 Day 5 網路寶石:AWS VPC 架構 Routes & Security (上)
    • 作者: 用圖片高效學程式
    • 系列:無限手套 AWS 版:掌控一切的 5 + 1 雲端必學主題
  9. +132 DAY19 - 在win10家用版上安裝Docker Desktop
    • 作者: rs6000
    • 系列:總是學不來的中年大叔,孤獨的自學之旅
  10. +125 從零開始的8-bit迷宮探險【Level 23】長老,這個水晶值多少錢?
    • 作者: 雪花冰
    • 系列:從零開始的8-bit迷宮探險!Swift SpriteKit 遊戲開發實戰

越來越多人完賽了!恭喜!
現在 Top 10 中的類型又變多了耶!


上一篇
#16 Automation (4)
下一篇
#18 用免費 Serverless 及 JavaScript 寫 Telegram 聊天機器人!
系列文
JavaScript Easy Go!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言